package com.moodair.pip.core;

import com.moodair.pip.core.annotation.InputComponent;
import com.moodair.pip.core.annotation.OutputComponent;
import com.moodair.pip.core.annotation.PluginComponent;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;


/**
 * @author MoodAir
 */
public class PipelineClassPathScanner extends ClassPathBeanDefinitionScanner {
    private final Set<String> pipelineNames;

    public PipelineClassPathScanner(BeanDefinitionRegistry registry, Set<String> pipelineNames) {
        super(registry);
        this.pipelineNames = pipelineNames;
    }

    public void registerFilters(String... basePackages) {
        super.resetFilters(false);
        addIncludeFilter(new NameAnnotationTypeFilter(InputComponent.class));
        addIncludeFilter(new NameAnnotationTypeFilter(OutputComponent.class));
        addIncludeFilter(new NameAnnotationTypeFilter(PluginComponent.class));
        super.doScan(basePackages);
    }

    private class NameAnnotationTypeFilter extends AnnotationTypeFilter {
        private final Logger log = LoggerFactory.getLogger(PipelineRegistrar.class);
        private final String annotationTypeName;
        private final String annotationTypeValue;

        public NameAnnotationTypeFilter(Class<? extends Annotation> annotationType) {
            super(annotationType);
            this.annotationTypeName = annotationType.getName();
            if (PluginComponent.class == annotationType) {
                annotationTypeValue = "plugin";
            } else if (InputComponent.class == annotationType) {
                annotationTypeValue = "input";
            } else if (OutputComponent.class == annotationType) {
                annotationTypeValue = "output";
            } else {
                throw new UnsupportedOperationException("不受支持的类型：" + annotationTypeName);
            }
        }

        @Override
        public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
            if (super.matchSelf(metadataReader)) {
                AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
                for (String annotationType : metadata.getAnnotationTypes()) {
                    if (annotationTypeName.equals(annotationType)) {
                        Map<String, Object> map = metadata.getAnnotationAttributes(annotationType);
                        if (map != null) {
                            String attrName;
                            if ("plugin".equals(annotationTypeValue)) {
                                attrName = "value";
                            } else {
                                attrName = "pipeline";
                            }
                            Object value = map.get(attrName);
                            if (value != null) {
                                boolean enable = pipelineNames.contains("pipeline." + annotationTypeValue + "." + value);
                                if (enable) {
                                    log.debug("load {} component {} class is {}", annotationTypeValue, value, metadataReader.getClassMetadata().getClassName());
                                }
                                return enable;
                            }
                        }
                        return false;
                    }
                }
            }
            return false;
        }
    }
}